import datetime
import sys

from typing import Dict
sys.path.extend(["F:/ML/BNC", "D:/BNC", "/www/wwwroot/BNC"])

from typing import Dict

from .exceptions.exceptions import IllegalArgsException
from .mappers import MarkStatisticMapper, StockCalendarMapper, TagRelaMapper
from .Utils.Fnc import *
from django.utils import timezone
from datetime import datetime as _dt

cur_timezone = timezone.get_current_timezone()

__mark_statistic_mapper = MarkStatisticMapper()
__stock_calendar_mapper = StockCalendarMapper()
__tag_rela_mapper = TagRelaMapper()
default_num = 1500
DATE_FORMAT = "%Y%m%d"
DATE_FORMAT_SPILT_BY_ = "%Y-%m-%d"

def market_temperature(start_date=None, end_date=None, size=None, input_date_format=DATE_FORMAT_SPILT_BY_) -> list:
    # 定义需要的列名， 保证数据库不会多返回列，其实也可以不做保证，只是为了显得专业
    limit_col_set = {'date', 'continuous_ration', 'second_high_limit', 'third_high_limit', 'forth_high_limit',
                     'fifth_high_limit', 'gaobiao_scale'}
    # 定义附加的返回参数
    start_date, end_date = generate_right_date_equence(start_date=start_date, end_date=end_date, default_size=size,
                                                       input_date_format=input_date_format)
    scale = 30

    _cur_datetime = _dt.now(tz=cur_timezone)
    max_date = _cur_datetime.date()
    end_date = min(end_date, max_date)

    # 需要抛出异常
    if (start_date is not None) and start_date > end_date:
        raise IllegalArgsException("开始时间小于结束时间")

    # 转化数据类型，格式化为20191209
    # start_date_s = datetime.date.strftime("%Y%m%d")
    # end_date_s = datetime.date.strftime("%Y%m%d")
    temp_res_from_db = __mark_statistic_mapper.get_market_temperature(start_date=start_date, end_date=end_date,
                                                                      )

    # 格式化为json格式的内容 ( {"date":'d1', "gaobiao_count":'gbc1'}, ) 列转行
    standard_pre_json_object = regroup_db_res_2_pre_json_data(db_dict_lis=temp_res_from_db)
    # 添加新的列进去
    standard_pre_json_object['gaobiao_scale'] = scale
    standard_pre_json_object['dieting_line'] = 250
    standard_pre_json_object['zhangting_line'] = 40
    standard_pre_json_object['shouyi_ratio_line'] = 5.00
    return standard_pre_json_object


def market_high_limit(start_date=None, end_date=None, size=None, input_date_format=DATE_FORMAT_SPILT_BY_) -> list:
    # 定义需要的列名， 保证数据库不会多返回列，其实也可以不做保证，只是为了显得专业
    # 定义附加的返回参数
    scale = 30
    start_date, end_date = generate_right_date_equence(start_date=start_date, end_date=end_date, default_size=size,
                                                       input_date_format=input_date_format)
    limit_col_set = {'date', 'continue_high_ratio', 'first_high_count', 'second_high_count', 'third_high_count',
                     'forth_high_count',
                     'fifth_high_count'}

    _cur_datetime = _dt.now(tz=cur_timezone)
    max_date = _cur_datetime.date()
    end_date = min(end_date, max_date)

    # 需要抛出异常
    if (start_date is not None) and start_date > end_date:
        raise IllegalArgsException("开始时间小于结束时间")

    # 转化数据类型，格式化为20191209
    # start_date_s = datetime.date.strftime("%Y%m%d")
    # end_date_s = datetime.date.strftime("%Y%m%d")
    temp_res_from_db = __mark_statistic_mapper.get_high_reach_high(start_date=start_date, end_date=end_date,
                                                                   )
    # 格式化为json格式的内容 ( {"date":'d1', "gaobiao_count":'gbc1'}, ) 列转行
    standard_pre_json_object = regroup_db_res_2_pre_json_data(temp_res_from_db, allowed_cols=limit_col_set)
    # 添加新的列进去
    standard_pre_json_object['gaobiao_scale'] = scale

    return standard_pre_json_object


def stock_calendar(start_date=None, end_date=None, size=None, input_date_format=DATE_FORMAT_SPILT_BY_) -> Dict[
    str, dict]:
    """ 暂时只返回每日排名前五并且标签出现频数大于等于5的标签 每天返回5个"""

    # 定义需要的列名， 保证数据库不会多返回列，其实也可以不做保证，只是为了显得专业
    # 定义附加的返回参数
    start_date, end_date = generate_right_date_equence(start_date=start_date, end_date=end_date, default_size=size,
                                                       input_date_format=input_date_format)
    max_date = _dt.now(tz=cur_timezone).date()
    end_date = min(end_date, max_date)

    # 需要抛出异常
    if (start_date is not None) and start_date > end_date:
        raise IllegalArgsException("开始时间小于结束时间")

    # 转化数据类型，格式化为20191209
    __temp_res = __stock_calendar_mapper.select_stock_calendar_from_db(start_date=start_date, end_date=end_date)
    # 对数据按照date进行分组处理， 因为没天的数据个数不一致
    _new_res = dict() #
    # {
    #     "data": [{
    #         "date": "2019-10-11",
    #         "tags_inc": [{
    #             "tag": "自定义",
    #             "incr": "22",
    #             "plate_info": {
    #                 "first_high_count": 1,
    #                 "second_high_count": 2,
    #                 "third_high_count": 3,
    #                 "forth_high_count": 4,
    #                 "fifth_high_count": 5
    #             }
    #         }]
    #     }]
    # }
    for one_row_ in __temp_res:
        date_ = str(one_row_['date'])
        _new_res.setdefault(date_,{"tags_inc":list()})
        _new_res[date_]['tags_inc'].append(one_row_)
        _new_res[date_]['date'] = date_
    return {'data':_new_res}


def tag_rela_code(tag , num ):
    def validate_default_values(tag,num):
        __default_num = 40
        __default_tag = ""
        r_t = __default_tag
        r_n = __default_num
        if tag :
            r_t = tag
        if num:
            r_n = num
        return str(r_t), int(r_n)
    tag, num = validate_default_values(tag, num)
    if not tag :
        return dict()
    # 对时间进行格式化
    _temp_res = __tag_rela_mapper.select_rela_codes(tag=tag, num = num)
    # 提取部分信息为一行 ,提取cur_count
    _cc = 0
    for one_line_ in _temp_res:
        if "cur_date" in one_line_:
            dat_ =str(one_line_["cur_date"])
            one_line_["cur_date"]= "{}-{}-{}".format(dat_[:4],dat_[4:6],dat_[6:8])
        if "cur_count" in one_line_:
            _cc = max(_cc , one_line_['cur_count'])

    return {"rela_code":_temp_res,'cur_count': _cc,'server_time':datetime.date.today()}

def code_rela_tag(code_):
    if not code_:
        return dict()
    # 对时间进行格式化
    _temp_res = __tag_rela_mapper.select_rela_tag(code_)
    # 提取部分信息为一行 ,提取cur_count
    _cc = 0
    for one_line_ in _temp_res:
        if "cur_date" in one_line_:
            dat_ = str(one_line_["cur_date"])
            one_line_["cur_date"] = "{}-{}-{}".format(dat_[:4], dat_[4:6], dat_[6:8])
        if "cur_count" in one_line_:
            _cc = max(_cc, one_line_['cur_count'])

    return {"rela_tag": _temp_res, 'cur_count': _cc, 'server_time': datetime.date.today()}


# class StockCalendarSerice:
#     @classmethod

def tag_rela_code_by_date_tag_plate(date, tag, plate):
    """ 特定的api接口，减小数据的大小 """
    if not date or not tag or not plate:
        raise IllegalArgsException("date ,tag, plate不能为空，现在参数为 : {}".format((date,tag,plate,)))
    date = datetime.datetime.strptime(date, DATE_FORMAT_SPILT_BY_).date()
    _temp_res = __tag_rela_mapper.select_rela_codes_by_dtp(date,tag,plate)
    # _temp_res => temp_res
    return _temp_res



def continue_stock_info(cur_date, cur_tag, FORMAT = DATE_FORMAT_SPILT_BY_):
    """ 特定的api接口，减小数据的大小 """
    if not cur_date or not cur_tag :
        raise IllegalArgsException("date ,tag, plate不能为空，现在参数为 : {}".format(locals()))
    cur_date = datetime.datetime.strptime(cur_date, DATE_FORMAT_SPILT_BY_).date()
    _temp_res = __tag_rela_mapper.select_continue_stock_infos(cur_date, cur_tag)
    # 进行分组重整
    map_index_2_name = {1: "first_high_count", 2: "second_high_count", 3: "third_high_count", 4: "forth_high_count",
                        5: "fifth_high_count"
                        }
    _new_res = dict()
    for v_ in list(map_index_2_name.values()):
        _new_res.setdefault(v_,list())
    for r_ in _temp_res:
        limit_count_ = r_['limit_count']
        if 4>=int(limit_count_)>=1:
            new_key_name_ = map_index_2_name[int(limit_count_)]
        elif int(limit_count_) >= 5:
            new_key_name_ = 'fifth_high_count'
        else:
            continue
        _new_res.setdefault(new_key_name_,list())
        _new_res[new_key_name_].append(r_)

    # _temp_res => temp_res
    return {"data":_new_res}

